package org.dromara;

import com.binance.connector.client.spot.websocket.api.model.AvgPriceRequest;
import com.binance.connector.client.spot.websocket.api.model.AvgPriceResponse;
import lombok.extern.slf4j.Slf4j;
import org.dromara.assets.service.impl.BinanceWebSocketWithNew;
import org.springframework.batch.core.*;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.job.builder.FlowBuilder;
import org.springframework.batch.core.job.builder.JobBuilder;
import org.springframework.batch.core.job.flow.Flow;
import org.springframework.batch.core.job.flow.FlowExecutionStatus;
import org.springframework.batch.core.job.flow.JobExecutionDecider;
import org.springframework.batch.core.job.flow.support.SimpleFlow;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.transaction.PlatformTransactionManager;

import java.math.BigDecimal;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

//@SpringBootApplication
//@EnableBatchProcessing
@Slf4j
public class TradingBatchApplication {

    public static void main(String[] args) {
        SpringApplication.run(TradingBatchApplication.class, args);
    }

    @Autowired
    private JobRepository jobRepository;

    @Autowired
    private PlatformTransactionManager transactionManager;

    @Autowired
    private JobLauncher jobLauncher;

    // 假设的外部服务或逻辑类，用于模拟业务操作
    private static class TradingService {
        boolean checkCoinPrice() {

            try {
                AvgPriceRequest request = new AvgPriceRequest().symbol("SOLFDUSD");
                CompletableFuture<AvgPriceResponse> responseCompletableFuture =
                        BinanceWebSocketWithNew.api.avgPrice(request);
                String price = responseCompletableFuture.get().getResult().getPrice();
                BigDecimal bigDecimal = new BigDecimal(price);
                if (bigDecimal.compareTo(new BigDecimal("196")) < 0) {
                    log.info("价格触发");
                } else {
                    log.info("价格过高");
                }

            } catch (Exception e) {
                e.printStackTrace();
            }

            log.info("Checking coin price at " + new java.util.Date());
            return Math.random() > 0.8; // 随机模拟
        }

        void redeemFromFinancialAccount() {
            log.info("Step 1: Redeeming from financial account...");
        }

        void performTransaction() {
            log.info("Step 2: Performing transaction...");
        }

        void placeOrder() {
            log.info("Step 3: Placing order...");
        }

        boolean checkTransactionStatusAndCoinPrice() {
            log.info("Checking transaction status and coin price...");
            return Math.random() > 0.1; // 随机模拟
        }

        void buyFinancialProduct() {
            log.info("Step 5: Buying financial product...");
        }
    }

    private TradingService tradingService = new TradingService();

    // 币价判断决策器
    @Bean
    public JobExecutionDecider coinPriceDecider() {
        return (jobExecution, stepExecution) -> {
            //先判断任务状态，如果状态为检测中，则继续检测逻辑，否则直接返回YES，进行下一下操作
            log.info("Executing coinPriceDecider...");
            if (tradingService.checkCoinPrice()) {
                return new FlowExecutionStatus("YES");
            } else {
                return new FlowExecutionStatus("NO");
            }
        };
    }

    // 成交和币价判断决策器
    @Bean
    public JobExecutionDecider transactionAndPriceDecider() {
        return (jobExecution, stepExecution) -> {
            if (tradingService.checkTransactionStatusAndCoinPrice()) {
                return new FlowExecutionStatus("NEED_STEP5");
            } else {
                return new FlowExecutionStatus("END");
            }
        };
    }

    // 步骤1: 从理财账户赎回
    @Bean
    public Step step1() {
        return new StepBuilder("step1", jobRepository)
                .tasklet((contribution, chunkContext) -> {
                    tradingService.redeemFromFinancialAccount();
                    return RepeatStatus.FINISHED;
                }, transactionManager)
                .build();
    }

    // 步骤2: 进行交易
    @Bean
    public Step step2() {
        return new StepBuilder("step2", jobRepository)
                .tasklet((contribution, chunkContext) -> {
                    tradingService.performTransaction();
                    return RepeatStatus.FINISHED;
                }, transactionManager)
                .build();
    }

    // 步骤3: 进行挂单
    @Bean
    public Step step3() {
        return new StepBuilder("step3", jobRepository)
                .tasklet((contribution, chunkContext) -> {
                    tradingService.placeOrder();
                    return RepeatStatus.FINISHED;
                }, transactionManager)
                .build();
    }

    // 步骤5: 购买理财产品
    @Bean
    public Step step5() {
        return new StepBuilder("step5", jobRepository)
                .tasklet((contribution, chunkContext) -> {
                    log.info("Executing step5...");
                    tradingService.buyFinancialProduct();
                    ExecutionContext executionContext = chunkContext.getStepContext().getStepExecution().getJobExecution().getExecutionContext();
                    executionContext.put("restart", true);
                    return RepeatStatus.FINISHED;
                }, transactionManager)
                .build();
    }

    // 重试步骤：模拟2分钟延迟
    @Bean
    public Step retryStep() {
        return new StepBuilder("retryStep", jobRepository)
                .tasklet((contribution, chunkContext) -> {
                    log.info("Retrying after 2 minutes...");
                    Thread.sleep(2000); // 2分钟延迟（仅用于演示，生产中避免）
                    return RepeatStatus.FINISHED;
                }, transactionManager)
                .build();
    }

   // @Bean
    public Job tradingJob() {
        log.info("Trading job...");
        return new JobBuilder("tradingJob", jobRepository)
                .start(coinPriceDecider())
                .on("NO").to(retryStep()).next(coinPriceDecider())
                .on("YES").to(step1())
                .next(step2())
                .next(step3())
                .next(transactionAndPriceDecider())
                .on("NEED_STEP5").to(step5()).next(coinPriceDecider())
                .on("END").end()
                .end()
                .build();
    }

    // 在 Spring Boot 启动时运行 Job
    //@Bean
    public ApplicationRunner jobRunner() {
        log.info("Trading job runner...");
        return args -> {
            CompletableFuture.runAsync(() -> {
                try {
                    log.info("Starting tradingJob on application startup at " + new java.util.Date());
                    JobParameters params = new JobParametersBuilder()
                            .addLong("time", System.currentTimeMillis())
                            .toJobParameters();
                    jobLauncher.run(tradingJob(), params);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
        };
    }
}